/* curses.c */

/* Author:
 *      Steve Kirkendall
 *      16820 SW Tallac Way
 *      Beaverton, OR 97006
 *      kirkenda@jove.cs.pdx.edu, or ...uunet!tektronix!psueea!jove!kirkenda
 */


/* This file contains the functions & variables needed for a tiny subset of
 * curses.  The principle advantage of this version of curses is its
 * extreme speed.  Disadvantages are potentially larger code, few supported
 * functions, limited compatibility with full curses, and only stdscr.
 */

#include "curses.h"
#include <signal.h>
#ifdef ARC
extern vdu();
#endif

extern char     *malloc();
extern char     *getenv();

/* variables, publicly available & used in the macros */
short   ospeed;         /* speed of the tty, eg B2400 */
WINDOW  *stdscr;        /* pointer into kbuf[] */
WINDOW  kbuf[KBSIZ];    /* a very large output buffer */
int     LINES;          /* :li#: number of rows */
int     COLS;           /* :co#: number of columns */
int     AM;             /* :am:  boolean: auto margins? */
int     PT;             /* :pt:  boolean: physical tabs? */
char    *VB="\033VB";   /* :vb=: visible bell */
char    *UP="\033UP";   /* :up=: move cursor up */
char    *SC="";         /* :sc=: save cursor position & char attributes */
char    *RC="";         /* :rc=: resore cursor position & char attributes */
char    *SO="";         /* :so=: standout start */
char    *SE="";         /* :se=: standout end */
char    *US="";         /* :us=: underline start */
char    *UE="";         /* :ue=: underline end */
char    *VB_s="";       /* :VB=: bold start */
char    *VB_e="";       /* :Vb=: bold end */
char    *AS="";         /* :as=: alternate (italic) start */
char    *AE="";         /* :ae=: alternate (italic) end */
char    *CM="\033CM";   /* :cm=: cursor movement */
char    *CE="\033CE";   /* :ce=: clear to end of line */
char    *CL="\033CL";   /* :cl=: home cursor & clear screen */
char    *CD="\033CD";   /* :cd=: clear to end of screen */
char    *AL="\033IL";   /* :al=: add a line */
char    *DL="\033DL";   /* :dl=: delete a line */
char    *SR="\033SR";   /* :sr=: scroll reverse */
char    *KU="\213";     /* :ku=: key sequence sent by up arrow */
char    *KD="\212";     /* :kd=: key sequence sent by down arrow */
char    *KL="\210";     /* :kl=: key sequence sent by left arrow */
char    *KR="\211";     /* :kr=: key sequence sent by right arrow */
char    *IM="";         /* :im=: insert mode start */
char    *IC="\033IC";   /* :ic=: insert the following character */
char    *EI="";         /* :ei=: insert mode end */
char    *IL="\033IL";   /* :il=: insert line */
char    *DC="\033DC";   /* :dc=: delete a character */
char    *aend="";       /* end an attribute -- either UE or VB_e */
char    ERASEKEY=127;   /* backspace key taken from ioctl structure */

static char     *capbuf;        /* capability string buffer */

initscr()
{
        /* make sure TERM variable is set */
        
        /* set cursor editing off */
        _kernel_osbyte(4,1,0);
        /* disable escape key */
        _kernel_osbyte(229,27,0);

	vdu("22,12");

	/* set cursor to block */
	vdu("23,0,10,96,0,0,0,0,0,0");

	/* set wrap off */
	vdu("23,16,1,254,0,0,0,0,0,0");

        /* start termcap stuff */
        starttcap();

        /* create stdscr and curscr */
        stdscr = kbuf;

        /* change the terminal mode to raw/noecho */
        resume_curses(TRUE);
}


endwin()
{
        /* change the terminal mode back the way it was */

        /* set cusor back to nornal */
        _kernel_osbyte(4,0,0);
        /* enable escape key */
        _kernel_osbyte(229,0,0);
	/* set cursor to line */
	vdu("23,0,10,103,0,0,0,0,0,0");
	/* set wrap on */
	vdu("23,16,0,254,0,0,0,0,0,0");

        suspend_curses();
}

suspend_curses()
{
        /* change the terminal mode back the way it was */
}

resume_curses(quietly)
        int     quietly;
{       
        char    *src, *dest;

        /* change the terminal mode to raw/noecho */

        if (quietly) return;

        /* Wait for a key from the user */
        for (dest = kbuf, src = tgoto(CM, 0, LINES - 1); *src; )
                *dest++ = *src++;
        for (src = SO; src && *src; )
                *dest++ = *src++;
        for (src = "[Press <RETURN> to continue]"; *src; )
                *dest++ = *src++;
        for (src = SE; src && *src; )
                *dest++ = *src++;
        write(1, kbuf, (int)(dest - kbuf));
        read(0, kbuf, 20); /* in RAW mode, so <20 is very likely */


        /* !!! special processing of the : key for Elvis' VI mode */
        if (kbuf[0] == ':')
        {
                ungetkey(':');
        }
}

static lacking(s)
        char    *s;
{
        write(2, "This termcap entry lacks the :", 30);
        write(2, s, 2);
        write(2, "=: capability\n", 14);
        exit(1);
}

starttcap()
{
        char    *str;
        static char     cbmem[800];
        
        getsize();

        /* allocate memory for capbuf */
        capbuf = cbmem;
        
}


/* This function gets the window size.  It uses the TIOCGWINSZ ioctl call if
 * your system has it, or tgetnum("li") and tgetnum("co") if it doesn't.
 * This function is called once during initialization, and thereafter it is
 * called whenever the SIGWINCH signal is sent to this process.
 */
getsize(signo)
        int     signo;
{
        /* reset the signal vector */

        /* get the window size, one way or another. */
        LINES = 32;
        COLS = 80;

        /* Make sure we got values that we can live with */
        if (LINES < 2 || COLS < 30)
        {
                write(2, "Screen too small\n", 17);
                endwin();
                exit(2);
        }
}


/* This is a function version of addch() -- it is used by tputs() */
int faddch(ch)
        int     ch;
{
        addch(ch);
}

#ifdef CRUNCH
/* These functions are equivelent to the macros of the same names... */

void qaddstr(str)
        char    *str;
{
        register char *s_, *d_;

        for (s_=(str), d_=stdscr; *d_++ = *s_++; )
        {
        }
        stdscr = d_ - 1;
}

void attrset(a)
        int     a;
{
        tputs(aend, 1, faddch);
        if (a == A_BOLD)
        {
                tputs(VB_s, 1, faddch);
                aend = VB_e;
        }
        else if (a == A_UNDERLINE)
        {
                tputs(US, 1, faddch);
                aend = UE;
        }
        else if (a == A_ALTCHARSET)
        {
                tputs(AS, 1, faddch);
                aend = AE;
        }
        else
        {
                aend = "";
        }
}


void insch(ch)
        int     ch;
{
/*        if (IM)
                tputs(IM, 1, faddch); */
        tputs(IC, 1, faddch);
        qaddch(ch);
        /* if (EI)
                tputs(EI, 1, faddch); */
}
#endif
